package ch.bfh.abcm.rems.sensors.tinkerforge.tfsensors;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.UnknownHostException;

import javax.swing.Timer;

import org.apache.log4j.Logger;

import ch.bfh.abcm.rems.interfaces.tinkerforge.TFSensor;
import ch.bfh.abcm.rems.interfaces.tinkerforge.TFSensorDataPersister;
import ch.bfh.abcm.rems.sensors.tinkerforge.TFSensorConfigDefinition;
import ch.bfh.abcm.rems.sensors.tinkerforge.TFSensorType;

import com.tinkerforge.BrickletAmbientLight;
import com.tinkerforge.IPConnection;
import com.tinkerforge.NotConnectedException;
import com.tinkerforge.TimeoutException;

public class REMSAmbientLightSensor extends BrickletAmbientLight implements TFSensor {

    private static final Logger logger = Logger.getLogger("play");

    private IPConnection connection;
    private String uid;
    private String host;
    private long callbackperiod;
    private int port;
    private TFSensorDataPersister sensorDataPersister;
    private Timer polling;

    public REMSAmbientLightSensor(String uid, IPConnection ipcon, String host, int port,
            TFSensorDataPersister persister, long callBackPeriod) {
        super(uid, ipcon);
        this.connection = ipcon;
        this.uid = uid;
        this.host = host;
        this.port = port;
        this.callbackperiod = callBackPeriod;
        this.sensorDataPersister = persister;
        this.polling = new Timer(TFSensorConfigDefinition.DEFAULT_CALL_BACK_PERIOD, new PollingAction());
        this.addIlluminanceListener(new LuxListener());
    }

    @Override
    public boolean connect() {
        boolean connected = false;
        try {
            logger.info("Connecting to Sensor " + uid + "...");
            connection.connect(host, port);
            connected = true;
        } catch (UnknownHostException e) {
            logger.error("UnknownHostException: " + e.getMessage());
        } catch (com.tinkerforge.AlreadyConnectedException e) {
            logger.error("AlreadyConnectedException: " + e.getMessage());
        } catch (IOException e) {
            logger.error("IOException: " + e.getMessage());
        }
        logger.info(">" + uid + " ("+TFSensorType.AMBIENT+") Connected<");
        if (connected) {
            polling.start();
        }
        return connected;
    }

    @Override
    public boolean disconnect() {
        boolean disconnected = false;
        try {
            logger.info("Disconnect Sensor " + uid + "...");
            connection.disconnect();
            disconnected = true;
        } catch (NotConnectedException e) {
            logger.error("NotConnectedException: " + e.getMessage());
        }
        logger.info(">" + uid + " Disconneced<");
        if (disconnected) {
            polling.stop();
        }
        return disconnected;
    }

    @Override
    public void setCallBackPeriod(long period) {
        try {
            this.setIlluminanceCallbackPeriod(period);
            logger.debug("Set CallbackPeriod to " + period);
        } catch (TimeoutException e) {
            logger.error("TimeoutException: " + e.getMessage());
        } catch (NotConnectedException e) {
            logger.error("NotConnectedException: " + e.getMessage());
        }
    }

    public IPConnection getConnection() {
        return connection;
    }

    public String getUid() {
        return uid;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    @Override
    public long getCallBackPeriod() {
        return callbackperiod;
    }


    private void saveData(int data){
        sensorDataPersister.saveSensorData(data, uid, host, TFSensorType.AMBIENT);
    }
    
    @Override
    public boolean isConnected() {
        if (connection == null) {
            logger.error("ipConnection for Sensor " + uid + " is Null");
            return false;
        }
        switch (connection.getConnectionState()) {
        case IPConnection.CONNECTION_STATE_CONNECTED:
            logger.debug("Sensor " + uid + "is connected");
            return true;
        default:
            logger.debug("Sensor " + uid + "is not connected");
            return false;
        }
    }

    @Override
    public String getUID() {
        return uid;
    }

    @Override
    public void startPolling() {
        polling.start();
    }

    @Override
    public void stopPolling() {
       polling.stop();
    }
    
    @Override
    public String toString() {
        return "REMSAmbientLightSensor [uid=" + uid + ", host=" + host + ", callbackperiod=" + callbackperiod + "]";
    }
    
    private class LuxListener implements IlluminanceListener {
        
        @Override
        public void illuminance(int illuminance) {
            saveData(illuminance);
        }
        
    }
    
    private class PollingAction implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                saveData(getIlluminance());
            } catch (TimeoutException e1) {
                logger.error("PollingAction: TimeoutException", e1);
            } catch (NotConnectedException e1) {
                logger.error("PollingAction: TimeoutException", e1);
            }
        }
        
    }

}
